home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / X11R4 / cmds / X / ddx / mi / misprite.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-20  |  49.7 KB  |  1,989 lines

  1. /*
  2.  * misprite.c
  3.  *
  4.  * machine independent software sprite routines
  5.  */
  6.  
  7. /* $XConsortium: misprite.c,v 5.28 90/01/13 17:33:32 rws Exp $ */
  8.  
  9. /*
  10. Copyright 1989 by the Massachusetts Institute of Technology
  11.  
  12. Permission to use, copy, modify, and distribute this software and its
  13. documentation for any purpose and without fee is hereby granted,
  14. provided that the above copyright notice appear in all copies and that
  15. both that copyright notice and this permission notice appear in
  16. supporting documentation, and that the name of M.I.T. not be used in
  17. advertising or publicity pertaining to distribution of the software
  18. without specific, written prior permission.  M.I.T. makes no
  19. representations about the suitability of this software for any
  20. purpose.  It is provided "as is" without express or implied warranty.
  21. */
  22.  
  23. # include   "X.h"
  24. # include   "Xproto.h"
  25. # include   "misc.h"
  26. # include   "pixmapstr.h"
  27. # include   "input.h"
  28. # include   "mi.h"
  29. # include   "cursorstr.h"
  30. # include   "font.h"
  31. # include   "scrnintstr.h"
  32. # include   "colormapst.h"
  33. # include   "windowstr.h"
  34. # include   "gcstruct.h"
  35. # include   "mipointer.h"
  36. # include   "mispritest.h"
  37. # include   "dixfontstr.h"
  38. # include   "fontstruct.h"
  39.  
  40. /*
  41.  * screen wrappers
  42.  */
  43.  
  44. static int  miSpriteScreenIndex;
  45. static unsigned long miSpriteGeneration = 0;
  46.  
  47. static Bool        miSpriteCloseScreen();
  48. static void        miSpriteGetImage();
  49. static void        miSpriteGetSpans();
  50. static void        miSpriteSourceValidate();
  51. static Bool        miSpriteCreateGC();
  52. static void        miSpriteBlockHandler();
  53. static void        miSpriteInstallColormap();
  54. static void        miSpriteStoreColors();
  55.  
  56. static void        miSpritePaintWindowBackground();
  57. static void        miSpritePaintWindowBorder();
  58. static void        miSpriteCopyWindow();
  59. static void        miSpriteClearToBackground();
  60.  
  61. static void        miSpriteSaveDoomedAreas();
  62. static RegionPtr    miSpriteRestoreAreas();
  63. static void        miSpriteComputeSaved();
  64.  
  65. #define SCREEN_PROLOGUE(pScreen, field)\
  66.   ((pScreen)->field = \
  67.    ((miSpriteScreenPtr) (pScreen)->devPrivates[miSpriteScreenIndex].ptr)->field)
  68.  
  69. #define SCREEN_EPILOGUE(pScreen, field, wrapper)\
  70.     ((pScreen)->field = wrapper)
  71.  
  72. /*
  73.  * GC func wrappers
  74.  */
  75.  
  76. static int  miSpriteGCIndex;
  77.  
  78. static void miSpriteValidateGC (),  miSpriteCopyGC ();
  79. static void miSpriteDestroyGC(),    miSpriteChangeGC();
  80. static void miSpriteChangeClip(),   miSpriteDestroyClip();
  81. static void miSpriteCopyClip();
  82.  
  83. static GCFuncs    miSpriteGCFuncs = {
  84.     miSpriteValidateGC,
  85.     miSpriteChangeGC,
  86.     miSpriteCopyGC,
  87.     miSpriteDestroyGC,
  88.     miSpriteChangeClip,
  89.     miSpriteDestroyClip,
  90.     miSpriteCopyClip,
  91. };
  92.  
  93. #define GC_FUNC_PROLOGUE(pGC)                    \
  94.     miSpriteGCPtr   pGCPriv =                    \
  95.     (miSpriteGCPtr) (pGC)->devPrivates[miSpriteGCIndex].ptr;\
  96.     (pGC)->funcs = pGCPriv->wrapFuncs;                \
  97.     if (pGCPriv->wrapOps)                    \
  98.     (pGC)->ops = pGCPriv->wrapOps;
  99.  
  100. #define GC_FUNC_EPILOGUE(pGC)                    \
  101.     pGCPriv->wrapFuncs = (pGC)->funcs;                \
  102.     (pGC)->funcs = &miSpriteGCFuncs;                \
  103.     if (pGCPriv->wrapOps)                    \
  104.     {                                \
  105.     pGCPriv->wrapOps = (pGC)->ops;                \
  106.     (pGC)->ops = &miSpriteGCOps;                \
  107.     }
  108.  
  109. /*
  110.  * GC op wrappers
  111.  */
  112.  
  113. static void        miSpriteFillSpans(),    miSpriteSetSpans();
  114. static void        miSpritePutImage();
  115. static RegionPtr    miSpriteCopyArea(),        miSpriteCopyPlane();
  116. static void        miSpritePolyPoint(),    miSpritePolylines();
  117. static void        miSpritePolySegment(),    miSpritePolyRectangle();
  118. static void        miSpritePolyArc(),        miSpriteFillPolygon();
  119. static void        miSpritePolyFillRect(),    miSpritePolyFillArc();
  120. static int        miSpritePolyText8(),    miSpritePolyText16();
  121. static void        miSpriteImageText8(),    miSpriteImageText16();
  122. static void        miSpriteImageGlyphBlt(),    miSpritePolyGlyphBlt();
  123. static void        miSpritePushPixels(),    miSpriteLineHelper();
  124. static void        miSpriteChangeClip(),    miSpriteDestroyClip();
  125. static void        miSpriteCopyClip();
  126.  
  127. static GCOps miSpriteGCOps = {
  128.     miSpriteFillSpans,        miSpriteSetSpans,        miSpritePutImage,    
  129.     miSpriteCopyArea,        miSpriteCopyPlane,        miSpritePolyPoint,
  130.     miSpritePolylines,        miSpritePolySegment,    miSpritePolyRectangle,
  131.     miSpritePolyArc,        miSpriteFillPolygon,    miSpritePolyFillRect,
  132.     miSpritePolyFillArc,    miSpritePolyText8,        miSpritePolyText16,
  133.     miSpriteImageText8,        miSpriteImageText16,    miSpriteImageGlyphBlt,
  134.     miSpritePolyGlyphBlt,   miSpritePushPixels,        miSpriteLineHelper,
  135. };
  136.  
  137. /*
  138.  * testing only -- remove cursor for every draw.  Eventually,
  139.  * each draw operation will perform a bounding box check against
  140.  * the saved cursor area
  141.  */
  142.  
  143. #define GC_SETUP_CHEAP(pDrawable)                    \
  144.     miSpriteScreenPtr    pScreenPriv = (miSpriteScreenPtr)        \
  145.     (pDrawable)->pScreen->devPrivates[miSpriteScreenIndex].ptr; \
  146.  
  147. #define GC_SETUP(pDrawable, pGC)                    \
  148.     GC_SETUP_CHEAP(pDrawable)                        \
  149.     miSpriteGCPtr    pGCPrivate = (miSpriteGCPtr)            \
  150.     (pGC)->devPrivates[miSpriteGCIndex].ptr;            \
  151.     GCFuncs *oldFuncs = pGC->funcs;
  152.  
  153. #define GC_SETUP_AND_CHECK(pDrawable, pGC)                \
  154.     GC_SETUP(pDrawable, pGC);                        \
  155.     if (GC_CHECK((WindowPtr)pDrawable))                    \
  156.     miSpriteRemoveCursor (pDrawable->pScreen);
  157.     
  158. #define GC_CHECK(pWin)                            \
  159.     (pScreenPriv->isUp &&                        \
  160.     (pWin)->drawable.x < pScreenPriv->saved.x2 &&            \
  161.     pScreenPriv->saved.x1 < (pWin)->drawable.x + (int) (pWin)->drawable.width && \
  162.     (pWin)->drawable.y < pScreenPriv->saved.y2 &&            \
  163.     pScreenPriv->saved.y1 < (pWin)->drawable.y + (int) (pWin)->drawable.height)
  164.  
  165. #define GC_OP_PROLOGUE(pGC) { \
  166.     (pGC)->funcs = pGCPrivate->wrapFuncs; \
  167.     (pGC)->ops = pGCPrivate->wrapOps; \
  168.     }
  169.  
  170. #define GC_OP_EPILOGUE(pGC) { \
  171.     pGCPrivate->wrapOps = (pGC)->ops; \
  172.     (pGC)->funcs = oldFuncs; \
  173.     (pGC)->ops = &miSpriteGCOps; \
  174.     }
  175.  
  176. /*
  177.  * pointer-sprite method table
  178.  */
  179.  
  180. static Bool miSpriteRealizeCursor (),    miSpriteUnrealizeCursor ();
  181. static void miSpriteDisplayCursor (),    miSpriteUndisplayCursor ();
  182.  
  183. miPointerSpriteFuncRec miSpritePointerFuncs = {
  184.     miSpriteRealizeCursor,
  185.     miSpriteUnrealizeCursor,
  186.     miSpriteDisplayCursor,
  187.     miSpriteUndisplayCursor
  188. };
  189.  
  190. /*
  191.  * other misc functions
  192.  */
  193.  
  194. static void miSpriteRemoveCursor (),    miSpriteRestoreCursor();
  195.  
  196. /*
  197.  * miSpriteInitialize -- called from device-dependent screen
  198.  * initialization proc after all of the function pointers have
  199.  * been stored in the screen structure.
  200.  */
  201.  
  202. Bool
  203. miSpriteInitialize (pScreen, spriteFuncs, pointerFuncs)
  204.     ScreenPtr            pScreen;
  205.     miSpriteCursorFuncPtr   spriteFuncs;
  206.     miPointerCursorFuncPtr  pointerFuncs;
  207. {
  208.     miSpriteScreenPtr    pPriv;
  209.     VisualPtr        pVisual;
  210.     int            i;
  211.     
  212.     if (miSpriteGeneration != serverGeneration)
  213.     {
  214.     miSpriteScreenIndex = AllocateScreenPrivateIndex ();
  215.     if (miSpriteScreenIndex < 0)
  216.         return FALSE;
  217.     miSpriteGeneration = serverGeneration;
  218.     miSpriteGCIndex = AllocateGCPrivateIndex ();
  219.     }
  220.     if (!AllocateGCPrivate(pScreen, miSpriteGCIndex, sizeof(miSpriteGCRec)))
  221.     return FALSE;
  222.     pPriv = (miSpriteScreenPtr) xalloc (sizeof (miSpriteScreenRec));
  223.     if (!pPriv)
  224.     return FALSE;
  225.     if (!miPointerInitialize (pScreen, &miSpritePointerFuncs, pointerFuncs))
  226.     {
  227.     xfree ((pointer) pPriv);
  228.     return FALSE;
  229.     }
  230.     pVisual = pScreen->visuals;
  231.     for (i = 0; i < pScreen->numVisuals; i++)
  232.     if (pVisual->vid == pScreen->rootVisual)
  233.         break;
  234.     pPriv->pVisual = pVisual;
  235.     pPriv->CloseScreen = pScreen->CloseScreen;
  236.     pPriv->GetImage = pScreen->GetImage;
  237.     pPriv->GetSpans = pScreen->GetSpans;
  238.     pPriv->SourceValidate = pScreen->SourceValidate;
  239.     pPriv->CreateGC = pScreen->CreateGC;
  240.     pPriv->BlockHandler = pScreen->BlockHandler;
  241.     pPriv->InstallColormap = pScreen->InstallColormap;
  242.     pPriv->StoreColors = pScreen->StoreColors;
  243.  
  244.     pPriv->PaintWindowBackground = pScreen->PaintWindowBackground;
  245.     pPriv->PaintWindowBorder = pScreen->PaintWindowBorder;
  246.     pPriv->CopyWindow = pScreen->CopyWindow;
  247.     pPriv->ClearToBackground = pScreen->ClearToBackground;
  248.  
  249.     pPriv->SaveDoomedAreas = pScreen->SaveDoomedAreas;
  250.     pPriv->RestoreAreas = pScreen->RestoreAreas;
  251.  
  252.     pPriv->pCursor = NULL;
  253.     pPriv->x = 0;
  254.     pPriv->y = 0;
  255.     pPriv->isUp = FALSE;
  256.     pPriv->shouldBeUp = FALSE;
  257.     pPriv->checkPixels = TRUE;
  258.     pPriv->pInstalledMap = NULL;
  259.     pPriv->pColormap = NULL;
  260.     pPriv->funcs = spriteFuncs;
  261.     pScreen->devPrivates[miSpriteScreenIndex].ptr = (pointer) pPriv;
  262.     pScreen->CloseScreen = miSpriteCloseScreen;
  263.     pScreen->GetImage = miSpriteGetImage;
  264.     pScreen->GetSpans = miSpriteGetSpans;
  265.     pScreen->SourceValidate = miSpriteSourceValidate;
  266.     pScreen->CreateGC = miSpriteCreateGC;
  267.     pScreen->BlockHandler = miSpriteBlockHandler;
  268.     pScreen->InstallColormap = miSpriteInstallColormap;
  269.     pScreen->StoreColors = miSpriteStoreColors;
  270.  
  271.     pScreen->PaintWindowBackground = miSpritePaintWindowBackground;
  272.     pScreen->PaintWindowBorder = miSpritePaintWindowBorder;
  273.     pScreen->CopyWindow = miSpriteCopyWindow;
  274.     pScreen->ClearToBackground = miSpriteClearToBackground;
  275.  
  276.     pScreen->SaveDoomedAreas = miSpriteSaveDoomedAreas;
  277.     pScreen->RestoreAreas = miSpriteRestoreAreas;
  278.  
  279.     return TRUE;
  280. }
  281.  
  282. /*
  283.  * Screen wrappers
  284.  */
  285.  
  286. /*
  287.  * CloseScreen wrapper -- unwrap everything, free the private data
  288.  * and call the wrapped function
  289.  */
  290.  
  291. static Bool
  292. miSpriteCloseScreen (i, pScreen)
  293.     ScreenPtr    pScreen;
  294. {
  295.     miSpriteScreenPtr   pScreenPriv;
  296.  
  297.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  298.  
  299.     pScreen->CloseScreen = pScreenPriv->CloseScreen;
  300.     pScreen->GetImage = pScreenPriv->GetImage;
  301.     pScreen->GetSpans = pScreenPriv->GetSpans;
  302.     pScreen->SourceValidate = pScreenPriv->SourceValidate;
  303.     pScreen->CreateGC = pScreenPriv->CreateGC;
  304.     pScreen->BlockHandler = pScreenPriv->BlockHandler;
  305.     pScreen->InstallColormap = pScreenPriv->InstallColormap;
  306.     pScreen->StoreColors = pScreenPriv->StoreColors;
  307.  
  308.     pScreen->PaintWindowBackground = pScreenPriv->PaintWindowBackground;
  309.     pScreen->PaintWindowBorder = pScreenPriv->PaintWindowBorder;
  310.     pScreen->CopyWindow = pScreenPriv->CopyWindow;
  311.     pScreen->ClearToBackground = pScreenPriv->ClearToBackground;
  312.  
  313.     pScreen->SaveDoomedAreas = pScreenPriv->SaveDoomedAreas;
  314.     pScreen->RestoreAreas = pScreenPriv->RestoreAreas;
  315.  
  316.     xfree ((pointer) pScreenPriv);
  317.  
  318.     return (*pScreen->CloseScreen) (i, pScreen);
  319. }
  320.  
  321. static void
  322. miSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine)
  323.     DrawablePtr        pDrawable;
  324.     int            sx, sy, w, h;
  325.     unsigned int    format;
  326.     unsigned long   planemask;
  327.     pointer        pdstLine;
  328. {
  329.     ScreenPtr        pScreen = pDrawable->pScreen;
  330.     miSpriteScreenPtr    pScreenPriv;
  331.     
  332.     SCREEN_PROLOGUE (pScreen, GetImage);
  333.  
  334.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  335.  
  336.     if (pDrawable->type == DRAWABLE_WINDOW &&
  337.         pScreenPriv->isUp &&
  338.     ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y, sx, sy, w, h))
  339.     {
  340.     miSpriteRemoveCursor (pScreen);
  341.     }
  342.  
  343.     (*pScreen->GetImage) (pDrawable, sx, sy, w, h,
  344.               format, planemask, pdstLine);
  345.  
  346.     SCREEN_EPILOGUE (pScreen, GetImage, miSpriteGetImage);
  347. }
  348.  
  349. static void
  350. miSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart)
  351.     DrawablePtr    pDrawable;
  352.     int        wMax;
  353.     DDXPointPtr    ppt;
  354.     int        *pwidth;
  355.     int        nspans;
  356.     unsigned int *pdstStart;
  357. {
  358.     ScreenPtr            pScreen = pDrawable->pScreen;
  359.     miSpriteScreenPtr        pScreenPriv;
  360.     
  361.     SCREEN_PROLOGUE (pScreen, GetSpans);
  362.  
  363.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  364.  
  365.     if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp)
  366.     {
  367.     register DDXPointPtr    pts;
  368.     register int        *widths;
  369.     register int        nPts;
  370.     register int        xorg,
  371.                 yorg;
  372.  
  373.     xorg = pDrawable->x;
  374.     yorg = pDrawable->y;
  375.  
  376.     for (pts = ppt, widths = pwidth, nPts = nspans;
  377.          nPts--;
  378.          pts++, widths++)
  379.      {
  380.         if (SPN_OVERLAP(&pScreenPriv->saved,pts->y+yorg,
  381.                  pts->x+xorg,*widths))
  382.         {
  383.         miSpriteRemoveCursor (pScreen);
  384.         break;
  385.         }
  386.     }
  387.     }
  388.  
  389.     (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
  390.  
  391.     SCREEN_EPILOGUE (pScreen, GetSpans, miSpriteGetSpans);
  392. }
  393.  
  394. static void
  395. miSpriteSourceValidate (pDrawable, x, y, width, height)
  396.     DrawablePtr    pDrawable;
  397.     int        x, y, width, height;
  398. {
  399.     ScreenPtr            pScreen = pDrawable->pScreen;
  400.     miSpriteScreenPtr        pScreenPriv;
  401.     
  402.     SCREEN_PROLOGUE (pScreen, SourceValidate);
  403.  
  404.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  405.  
  406.     if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp &&
  407.     ORG_OVERLAP(&pScreenPriv->saved, pDrawable->x, pDrawable->y,
  408.             x, y, width, height))
  409.     {
  410.     miSpriteRemoveCursor (pScreen);
  411.     }
  412.  
  413.     if (pScreen->SourceValidate)
  414.     (*pScreen->SourceValidate) (pDrawable, x, y, width, height);
  415.  
  416.     SCREEN_EPILOGUE (pScreen, SourceValidate, miSpriteSourceValidate);
  417. }
  418.  
  419. static Bool
  420. miSpriteCreateGC (pGC)
  421.     GCPtr   pGC;
  422. {
  423.     ScreenPtr        pScreen = pGC->pScreen;
  424.     Bool        ret;
  425.     miSpriteGCPtr   pPriv;
  426.  
  427.     SCREEN_PROLOGUE (pScreen, CreateGC);
  428.     
  429.     pPriv = (miSpriteGCPtr)pGC->devPrivates[miSpriteGCIndex].ptr;
  430.  
  431.     ret = (*pScreen->CreateGC) (pGC);
  432.  
  433.     pPriv->wrapOps = NULL;
  434.     pPriv->wrapFuncs = pGC->funcs;
  435.     pGC->funcs = &miSpriteGCFuncs;
  436.  
  437.     SCREEN_EPILOGUE (pScreen, CreateGC, miSpriteCreateGC);
  438.  
  439.     return ret;
  440. }
  441.  
  442. static void
  443. miSpriteBlockHandler (i, blockData, pTimeout, pReadmask)
  444.     int    i;
  445.     pointer    blockData;
  446.     pointer    pTimeout;
  447.     pointer    pReadmask;
  448. {
  449.     ScreenPtr        pScreen = screenInfo.screens[i];
  450.     miSpriteScreenPtr    pPriv;
  451.  
  452.     pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  453.  
  454.     SCREEN_PROLOGUE(pScreen, BlockHandler);
  455.     
  456.     (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
  457.  
  458.     SCREEN_EPILOGUE(pScreen, BlockHandler, miSpriteBlockHandler);
  459.  
  460.     if (!pPriv->isUp && pPriv->shouldBeUp)
  461.     miSpriteRestoreCursor (pScreen);
  462. }
  463.  
  464. static void
  465. miSpriteInstallColormap (pMap)
  466.     ColormapPtr    pMap;
  467. {
  468.     ScreenPtr        pScreen = pMap->pScreen;
  469.     miSpriteScreenPtr    pPriv;
  470.  
  471.     pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  472.  
  473.     SCREEN_PROLOGUE(pScreen, InstallColormap);
  474.     
  475.     (*pScreen->InstallColormap) (pMap);
  476.  
  477.     SCREEN_EPILOGUE(pScreen, InstallColormap, miSpriteInstallColormap);
  478.  
  479.     if (pPriv->pColormap != pMap)
  480.     {
  481.         pPriv->pInstalledMap = pMap;
  482.         pPriv->checkPixels = TRUE;
  483.     if (pPriv->isUp && pPriv->shouldBeUp)
  484.         miSpriteRemoveCursor (pScreen);
  485.     }
  486. }
  487.  
  488. static void
  489. miSpriteStoreColors (pMap, ndef, pdef)
  490.     ColormapPtr    pMap;
  491.     int        ndef;
  492.     xColorItem    *pdef;
  493. {
  494.     ScreenPtr        pScreen = pMap->pScreen;
  495.     miSpriteScreenPtr    pPriv;
  496.     int            i;
  497.  
  498.     pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  499.  
  500.     SCREEN_PROLOGUE(pScreen, StoreColors);
  501.     
  502.     (*pScreen->StoreColors) (pMap, ndef, pdef);
  503.  
  504.     SCREEN_EPILOGUE(pScreen, StoreColors, miSpriteStoreColors);
  505.  
  506.     if (pPriv->pColormap == pMap)
  507.     {
  508.     for (i = 0; i < ndef; i++)
  509.         /*
  510.          * XXX direct color will affect pixels other than
  511.          * pdef[i].pixel -- this will be more difficult...
  512.          */
  513.         if (pdef[i].pixel == pPriv->colors[SOURCE_COLOR].pixel ||
  514.             pdef[i].pixel == pPriv->colors[MASK_COLOR].pixel)
  515.         {
  516.         pPriv->checkPixels = TRUE;
  517.         if (pPriv->isUp && pPriv->shouldBeUp)
  518.             miSpriteRemoveCursor (pScreen);
  519.         break;
  520.         }
  521.     }
  522. }
  523.  
  524. static void
  525. miSpriteFindColors (pScreen)
  526.     ScreenPtr    pScreen;
  527. {
  528.     miSpriteScreenPtr    pScreenPriv = (miSpriteScreenPtr)
  529.                 pScreen->devPrivates[miSpriteScreenIndex].ptr;
  530.     CursorPtr        pCursor;
  531.     xColorItem        *sourceColor, *maskColor;
  532.  
  533.     pCursor = pScreenPriv->pCursor;
  534.     sourceColor = &pScreenPriv->colors[SOURCE_COLOR];
  535.     maskColor = &pScreenPriv->colors[MASK_COLOR];
  536.     if (!(pCursor->foreRed == sourceColor->red &&
  537.       pCursor->foreGreen == sourceColor->green &&
  538.           pCursor->foreBlue == sourceColor->blue &&
  539.       pCursor->backRed == maskColor->red &&
  540.       pCursor->backGreen == maskColor->green &&
  541.       pCursor->backBlue == maskColor->blue) ||
  542.      pScreenPriv->pColormap != pScreenPriv->pInstalledMap)
  543.     {
  544.     pScreenPriv->pColormap = pScreenPriv->pInstalledMap;
  545.     sourceColor->red = pCursor->foreRed;
  546.     sourceColor->green = pCursor->foreGreen;
  547.     sourceColor->blue = pCursor->foreBlue;
  548.     FakeAllocColor (pScreenPriv->pColormap, sourceColor);
  549.     maskColor->red = pCursor->backRed;
  550.     maskColor->green = pCursor->backGreen;
  551.     maskColor->blue = pCursor->backBlue;
  552.     FakeAllocColor (pScreenPriv->pColormap, maskColor);
  553.     /* "free" the pixels right away, don't let this confuse you */
  554.     FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel);
  555.     FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel);
  556.     }
  557.     pScreenPriv->checkPixels = FALSE;
  558. }
  559.  
  560. /*
  561.  * BackingStore wrappers
  562.  */
  563.  
  564. static void
  565. miSpriteSaveDoomedAreas (pWin, pObscured, dx, dy)
  566.     WindowPtr    pWin;
  567.     RegionPtr    pObscured;
  568.     int        dx, dy;
  569. {
  570.     ScreenPtr        pScreen;
  571.     miSpriteScreenPtr   pScreenPriv;
  572.     BoxRec        cursorBox;
  573.  
  574.     pScreen = pWin->drawable.pScreen;
  575.     
  576.     SCREEN_PROLOGUE (pScreen, SaveDoomedAreas);
  577.  
  578.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  579.     if (pScreenPriv->isUp)
  580.     {
  581.     cursorBox = pScreenPriv->saved;
  582.  
  583.     if (dx || dy)
  584.      {
  585.         cursorBox.x1 += dx;
  586.         cursorBox.y1 += dy;
  587.         cursorBox.x2 += dx;
  588.         cursorBox.y2 += dy;
  589.     }
  590.     if ((* pScreen->RectIn) (pObscured, &cursorBox) != rgnOUT)
  591.         miSpriteRemoveCursor (pScreen);
  592.     }
  593.  
  594.     (*pScreen->SaveDoomedAreas) (pWin, pObscured, dx, dy);
  595.  
  596.     SCREEN_EPILOGUE (pScreen, SaveDoomedAreas, miSpriteSaveDoomedAreas);
  597. }
  598.  
  599. static RegionPtr
  600. miSpriteRestoreAreas (pWin, prgnExposed)
  601.     WindowPtr    pWin;
  602.     RegionPtr    prgnExposed;
  603. {
  604.     ScreenPtr        pScreen;
  605.     miSpriteScreenPtr   pScreenPriv;
  606.     RegionPtr        result;
  607.  
  608.     pScreen = pWin->drawable.pScreen;
  609.     
  610.     SCREEN_PROLOGUE (pScreen, RestoreAreas);
  611.  
  612.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  613.     if (pScreenPriv->isUp)
  614.     {
  615.     if ((* pScreen->RectIn) (prgnExposed, &pScreenPriv->saved) != rgnOUT)
  616.         miSpriteRemoveCursor (pScreen);
  617.     }
  618.  
  619.     result = (*pScreen->RestoreAreas) (pWin, prgnExposed);
  620.  
  621.     SCREEN_EPILOGUE (pScreen, RestoreAreas, miSpriteRestoreAreas);
  622.  
  623.     return result;
  624. }
  625.  
  626. /*
  627.  * Window wrappers
  628.  */
  629.  
  630. static void
  631. miSpritePaintWindowBackground (pWin, pRegion, what)
  632.     WindowPtr    pWin;
  633.     RegionPtr    pRegion;
  634.     int        what;
  635. {
  636.     ScreenPtr        pScreen;
  637.     miSpriteScreenPtr    pScreenPriv;
  638.  
  639.     pScreen = pWin->drawable.pScreen;
  640.  
  641.     SCREEN_PROLOGUE (pScreen, PaintWindowBackground);
  642.  
  643.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  644.     if (pScreenPriv->isUp)
  645.     {
  646.     /*
  647.      * If the cursor is on the same screen as the window, check the
  648.      * region to paint for the cursor and remove it as necessary
  649.      */
  650.     if ((* pScreen->RectIn) (pRegion, &pScreenPriv->saved) != rgnOUT)
  651.         miSpriteRemoveCursor (pScreen);
  652.     }
  653.  
  654.     (*pScreen->PaintWindowBackground) (pWin, pRegion, what);
  655.  
  656.     SCREEN_EPILOGUE (pScreen, PaintWindowBackground, miSpritePaintWindowBackground);
  657. }
  658.  
  659. static void
  660. miSpritePaintWindowBorder (pWin, pRegion, what)
  661.     WindowPtr    pWin;
  662.     RegionPtr    pRegion;
  663.     int        what;
  664. {
  665.     ScreenPtr        pScreen;
  666.     miSpriteScreenPtr    pScreenPriv;
  667.  
  668.     pScreen = pWin->drawable.pScreen;
  669.  
  670.     SCREEN_PROLOGUE (pScreen, PaintWindowBorder);
  671.  
  672.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  673.     if (pScreenPriv->isUp)
  674.     {
  675.     /*
  676.      * If the cursor is on the same screen as the window, check the
  677.      * region to paint for the cursor and remove it as necessary
  678.      */
  679.     if ((* pScreen->RectIn) (pRegion, &pScreenPriv->saved) != rgnOUT)
  680.         miSpriteRemoveCursor (pScreen);
  681.     }
  682.  
  683.     (*pScreen->PaintWindowBorder) (pWin, pRegion, what);
  684.  
  685.     SCREEN_EPILOGUE (pScreen, PaintWindowBorder, miSpritePaintWindowBorder);
  686. }
  687.  
  688. static void
  689. miSpriteCopyWindow (pWin, ptOldOrg, pRegion)
  690.     WindowPtr    pWin;
  691.     DDXPointRec    ptOldOrg;
  692.     RegionPtr    pRegion;
  693. {
  694.     ScreenPtr        pScreen;
  695.     miSpriteScreenPtr    pScreenPriv;
  696.     BoxRec        cursorBox;
  697.     int            dx, dy;
  698.  
  699.     pScreen = pWin->drawable.pScreen;
  700.  
  701.     SCREEN_PROLOGUE (pScreen, CopyWindow);
  702.  
  703.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  704.     if (pScreenPriv->isUp)
  705.     {
  706.     /*
  707.      * check both the source and the destination areas.  The given
  708.      * region is source relative, so offset the cursor box by
  709.      * the delta position
  710.      */
  711.     cursorBox = pScreenPriv->saved;
  712.     dx = pWin->drawable.x - ptOldOrg.x;
  713.     dy = pWin->drawable.y - ptOldOrg.y;
  714.     cursorBox.x1 -= dx;
  715.     cursorBox.x2 -= dx;
  716.     cursorBox.y1 -= dy;
  717.     cursorBox.y2 -= dy;
  718.     if ((* pScreen->RectIn) (pRegion, &pScreenPriv->saved) != rgnOUT ||
  719.         (* pScreen->RectIn) (pRegion, &cursorBox) != rgnOUT)
  720.         miSpriteRemoveCursor (pScreen);
  721.     }
  722.  
  723.     (*pScreen->CopyWindow) (pWin, ptOldOrg, pRegion);
  724.  
  725.     SCREEN_EPILOGUE (pScreen, CopyWindow, miSpriteCopyWindow);
  726. }
  727.  
  728. static void
  729. miSpriteClearToBackground (pWin, x, y, w, h, generateExposures)
  730.     WindowPtr pWin;
  731.     short x,y;
  732.     unsigned short w,h;
  733.     Bool generateExposures;
  734. {
  735.     ScreenPtr        pScreen;
  736.     miSpriteScreenPtr    pScreenPriv;
  737.     int            realw, realh;
  738.  
  739.     pScreen = pWin->drawable.pScreen;
  740.  
  741.     SCREEN_PROLOGUE (pScreen, ClearToBackground);
  742.  
  743.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  744.     if (pScreenPriv->isUp)
  745.     {
  746.     if (!(realw = w))
  747.         realw = (int) pWin->drawable.width - x;
  748.     if (!(realh = h))
  749.         realh = (int) pWin->drawable.height - y;
  750.     if (ORG_OVERLAP(&pScreenPriv->saved, pWin->drawable.x, pWin->drawable.y,
  751.             x, y, realw, realh))
  752.     {
  753.         miSpriteRemoveCursor (pScreen);
  754.     }
  755.     }
  756.  
  757.     (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures);
  758.  
  759.     SCREEN_EPILOGUE (pScreen, ClearToBackground, miSpriteClearToBackground);
  760. }
  761.  
  762. /*
  763.  * GC Func wrappers
  764.  */
  765.  
  766. static void
  767. miSpriteValidateGC (pGC, changes, pDrawable)
  768.     GCPtr    pGC;
  769.     Mask    changes;
  770.     DrawablePtr    pDrawable;
  771. {
  772.     GC_FUNC_PROLOGUE (pGC);
  773.  
  774.     (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable);
  775.     
  776.     pGCPriv->wrapOps = NULL;
  777.     if (pDrawable->type == DRAWABLE_WINDOW && ((WindowPtr) pDrawable)->viewable)
  778.     {
  779.     WindowPtr   pWin;
  780.     RegionPtr   pRegion;
  781.  
  782.     pWin = (WindowPtr) pDrawable;
  783.     pRegion = &pWin->clipList;
  784.     if (pGC->subWindowMode == IncludeInferiors)
  785.         pRegion = &pWin->borderClip;
  786.     if ((*pDrawable->pScreen->RegionNotEmpty) (pRegion))
  787.         pGCPriv->wrapOps = pGC->ops;
  788.     }
  789.  
  790.     GC_FUNC_EPILOGUE (pGC);
  791. }
  792.  
  793. static void
  794. miSpriteChangeGC (pGC, mask)
  795.     GCPtr        pGC;
  796.     unsigned long   mask;
  797. {
  798.     GC_FUNC_PROLOGUE (pGC);
  799.  
  800.     (*pGC->funcs->ChangeGC) (pGC, mask);
  801.     
  802.     GC_FUNC_EPILOGUE (pGC);
  803. }
  804.  
  805. static void
  806. miSpriteCopyGC (pGCSrc, mask, pGCDst)
  807.     GCPtr        pGCSrc, pGCDst;
  808.     unsigned long   mask;
  809. {
  810.     GC_FUNC_PROLOGUE (pGCDst);
  811.  
  812.     (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
  813.     
  814.     GC_FUNC_EPILOGUE (pGCDst);
  815. }
  816.  
  817. static void
  818. miSpriteDestroyGC (pGC)
  819.     GCPtr   pGC;
  820. {
  821.     GC_FUNC_PROLOGUE (pGC);
  822.  
  823.     (*pGC->funcs->DestroyGC) (pGC);
  824.     
  825.     GC_FUNC_EPILOGUE (pGC);
  826. }
  827.  
  828. static void
  829. miSpriteChangeClip (pGC, type, pvalue, nrects)
  830.     GCPtr   pGC;
  831.     int        type;
  832.     pointer    pvalue;
  833.     int        nrects;
  834. {
  835.     GC_FUNC_PROLOGUE (pGC);
  836.  
  837.     (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
  838.  
  839.     GC_FUNC_EPILOGUE (pGC);
  840. }
  841.  
  842. static void
  843. miSpriteCopyClip(pgcDst, pgcSrc)
  844.     GCPtr pgcDst, pgcSrc;
  845. {
  846.     GC_FUNC_PROLOGUE (pgcDst);
  847.  
  848.     (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
  849.  
  850.     GC_FUNC_EPILOGUE (pgcDst);
  851. }
  852.  
  853. static void
  854. miSpriteDestroyClip(pGC)
  855.     GCPtr    pGC;
  856. {
  857.     GC_FUNC_PROLOGUE (pGC);
  858.  
  859.     (* pGC->funcs->DestroyClip)(pGC);
  860.  
  861.     GC_FUNC_EPILOGUE (pGC);
  862. }
  863.  
  864. /*
  865.  * GC Op wrappers
  866.  */
  867.  
  868. static void
  869. miSpriteFillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted)
  870.     DrawablePtr pDrawable;
  871.     GCPtr    pGC;
  872.     int        nInit;            /* number of spans to fill */
  873.     DDXPointPtr pptInit;        /* pointer to list of start points */
  874.     int        *pwidthInit;        /* pointer to list of n widths */
  875.     int     fSorted;
  876. {
  877.     GC_SETUP(pDrawable, pGC);
  878.  
  879.     if (GC_CHECK((WindowPtr) pDrawable))
  880.     {
  881.     register DDXPointPtr    pts;
  882.     register int        *widths;
  883.     register int        nPts;
  884.  
  885.     for (pts = pptInit, widths = pwidthInit, nPts = nInit;
  886.          nPts--;
  887.          pts++, widths++)
  888.      {
  889.          if (SPN_OVERLAP(&pScreenPriv->saved,pts->y,pts->x,*widths))
  890.          {
  891.          miSpriteRemoveCursor (pDrawable->pScreen);
  892.          break;
  893.          }
  894.     }
  895.     }
  896.  
  897.     GC_OP_PROLOGUE (pGC);
  898.  
  899.     (*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
  900.  
  901.     GC_OP_EPILOGUE (pGC);
  902. }
  903.  
  904. static void
  905. miSpriteSetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted)
  906.     DrawablePtr        pDrawable;
  907.     GCPtr        pGC;
  908.     int            *psrc;
  909.     register DDXPointPtr ppt;
  910.     int            *pwidth;
  911.     int            nspans;
  912.     int            fSorted;
  913. {
  914.     GC_SETUP(pDrawable, pGC);
  915.  
  916.     if (GC_CHECK((WindowPtr) pDrawable))
  917.     {
  918.     register DDXPointPtr    pts;
  919.     register int        *widths;
  920.     register int        nPts;
  921.  
  922.     for (pts = ppt, widths = pwidth, nPts = nspans;
  923.          nPts--;
  924.          pts++, widths++)
  925.      {
  926.          if (SPN_OVERLAP(&pScreenPriv->saved,pts->y,pts->x,*widths))
  927.          {
  928.          miSpriteRemoveCursor(pDrawable->pScreen);
  929.          break;
  930.          }
  931.     }
  932.     }
  933.  
  934.     GC_OP_PROLOGUE (pGC);
  935.  
  936.     (*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
  937.  
  938.     GC_OP_EPILOGUE (pGC);
  939. }
  940.  
  941. static void
  942. miSpritePutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits)
  943.     DrawablePtr      pDrawable;
  944.     GCPtr         pGC;
  945.     int          depth;
  946.     int              x;
  947.     int              y;
  948.     int              w;
  949.     int              h;
  950.     int              format;
  951.     char          *pBits;
  952. {
  953.     GC_SETUP(pDrawable, pGC);
  954.  
  955.     if (GC_CHECK((WindowPtr) pDrawable))
  956.     {
  957.     if (ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y,
  958.             x,y,w,h))
  959.      {
  960.         miSpriteRemoveCursor (pDrawable->pScreen);
  961.     }
  962.     }
  963.  
  964.     GC_OP_PROLOGUE (pGC);
  965.  
  966.     (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits);
  967.  
  968.     GC_OP_EPILOGUE (pGC);
  969. }
  970.  
  971. static RegionPtr
  972. miSpriteCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty)
  973.     DrawablePtr      pSrc;
  974.     DrawablePtr      pDst;
  975.     GCPtr         pGC;
  976.     int              srcx;
  977.     int              srcy;
  978.     int              w;
  979.     int              h;
  980.     int              dstx;
  981.     int              dsty;
  982. {
  983.     RegionPtr rgn;
  984.  
  985.     GC_SETUP(pDst, pGC);
  986.  
  987.     /* check destination/source overlap. */
  988.     if (GC_CHECK((WindowPtr) pDst) &&
  989.      (ORG_OVERLAP(&pScreenPriv->saved,pDst->x,pDst->y,dstx,dsty,w,h) ||
  990.       ((pDst == pSrc) &&
  991.        ORG_OVERLAP(&pScreenPriv->saved,pSrc->x,pSrc->y,srcx,srcy,w,h))))
  992.     {
  993.     miSpriteRemoveCursor (pDst->pScreen);
  994.     }
  995.  
  996.     GC_OP_PROLOGUE (pGC);
  997.  
  998.     rgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h,
  999.                  dstx, dsty);
  1000.  
  1001.     GC_OP_EPILOGUE (pGC);
  1002.  
  1003.     return rgn;
  1004. }
  1005.  
  1006. static RegionPtr
  1007. miSpriteCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane)
  1008.     DrawablePtr      pSrc;
  1009.     DrawablePtr      pDst;
  1010.     register GC   *pGC;
  1011.     int           srcx,
  1012.           srcy;
  1013.     int           w,
  1014.           h;
  1015.     int           dstx,
  1016.           dsty;
  1017.     unsigned long  plane;
  1018. {
  1019.     RegionPtr rgn;
  1020.  
  1021.     GC_SETUP(pDst, pGC);
  1022.  
  1023.     /*
  1024.      * check destination/source for overlap.
  1025.      */
  1026.     if (GC_CHECK((WindowPtr) pDst) &&
  1027.     (ORG_OVERLAP(&pScreenPriv->saved,pDst->x,pDst->y,dstx,dsty,w,h) ||
  1028.      ((pDst == pSrc) &&
  1029.       ORG_OVERLAP(&pScreenPriv->saved,pSrc->x,pSrc->y,srcx,srcy,w,h))))
  1030.     {
  1031.     miSpriteRemoveCursor (pDst->pScreen);
  1032.     }
  1033.  
  1034.     GC_OP_PROLOGUE (pGC);
  1035.  
  1036.     rgn = (*pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h,
  1037.                   dstx, dsty, plane);
  1038.  
  1039.     GC_OP_EPILOGUE (pGC);
  1040.  
  1041.     return rgn;
  1042. }
  1043.  
  1044. static void
  1045. miSpritePolyPoint (pDrawable, pGC, mode, npt, pptInit)
  1046.     DrawablePtr pDrawable;
  1047.     GCPtr    pGC;
  1048.     int        mode;        /* Origin or Previous */
  1049.     int        npt;
  1050.     xPoint     *pptInit;
  1051. {
  1052.     xPoint    t;
  1053.     int        n;
  1054.     BoxRec    cursor;
  1055.     register xPoint *pts;
  1056.  
  1057.     GC_SETUP (pDrawable, pGC);
  1058.  
  1059.     if (npt && GC_CHECK((WindowPtr) pDrawable))
  1060.     {
  1061.     cursor.x1 = pScreenPriv->saved.x1 - pDrawable->x;
  1062.     cursor.y1 = pScreenPriv->saved.y1 - pDrawable->y;
  1063.     cursor.x2 = pScreenPriv->saved.x2 - pDrawable->x;
  1064.     cursor.y2 = pScreenPriv->saved.y2 - pDrawable->y;
  1065.  
  1066.     if (mode == CoordModePrevious)
  1067.     {
  1068.         t.x = 0;
  1069.         t.y = 0;
  1070.         for (pts = pptInit, n = npt; n--; pts++)
  1071.         {
  1072.         t.x += pts->x;
  1073.         t.y += pts->y;
  1074.         if (cursor.x1 <= t.x && t.x <= cursor.x2 &&
  1075.             cursor.y1 <= t.y && t.y <= cursor.y2)
  1076.         {
  1077.             miSpriteRemoveCursor (pDrawable->pScreen);
  1078.             break;
  1079.         }
  1080.         }
  1081.     }
  1082.     else
  1083.     {
  1084.         for (pts = pptInit, n = npt; n--; pts++)
  1085.         {
  1086.         if (cursor.x1 <= pts->x && pts->x <= cursor.x2 &&
  1087.             cursor.y1 <= pts->y && pts->y <= cursor.y2)
  1088.         {
  1089.             miSpriteRemoveCursor (pDrawable->pScreen);
  1090.             break;
  1091.         }
  1092.         }
  1093.     }
  1094.     }
  1095.  
  1096.     GC_OP_PROLOGUE (pGC);
  1097.  
  1098.     (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pptInit);
  1099.  
  1100.     GC_OP_EPILOGUE (pGC);
  1101. }
  1102.  
  1103. static void
  1104. miSpritePolylines (pDrawable, pGC, mode, npt, pptInit)
  1105.     DrawablePtr      pDrawable;
  1106.     GCPtr         pGC;
  1107.     int              mode;
  1108.     int              npt;
  1109.     DDXPointPtr      pptInit;
  1110. {
  1111.     BoxPtr  cursor;
  1112.     register DDXPointPtr pts;
  1113.     int        n;
  1114.     int        x, y, x1, y1, x2, y2;
  1115.     int        lw;
  1116.     int        extra;
  1117.  
  1118.     GC_SETUP (pDrawable, pGC);
  1119.  
  1120.     if (npt && GC_CHECK((WindowPtr) pDrawable))
  1121.     {
  1122.     cursor = &pScreenPriv->saved;
  1123.     lw = pGC->lineWidth;
  1124.     x = pptInit->x + pDrawable->x;
  1125.     y = pptInit->y + pDrawable->y;
  1126.  
  1127.     if (npt == 1)
  1128.     {
  1129.         extra = lw >> 1;
  1130.         if (LINE_OVERLAP(cursor, x, y, x, y, extra))
  1131.         miSpriteRemoveCursor (pDrawable->pScreen);
  1132.     }
  1133.     else
  1134.     {
  1135.         extra = lw >> 1;
  1136.         /*
  1137.          * mitered joins can project quite a way from
  1138.          * the line end; the 11 degree miter limit limits
  1139.          * this extension to 10.43 * lw / 2, rounded up
  1140.          * and converted to int yields 6 * lw
  1141.          */
  1142.         if (pGC->joinStyle == JoinMiter)
  1143.         extra = 6 * lw;
  1144.         else if (pGC->capStyle == CapProjecting)
  1145.         extra = lw;
  1146.         for (pts = pptInit + 1, n = npt - 1; n--; pts++)
  1147.         {
  1148.         x1 = x;
  1149.         y1 = y;
  1150.         if (mode == CoordModeOrigin)
  1151.         {
  1152.             x2 = pDrawable->x + pts->x;
  1153.             y2 = pDrawable->y + pts->y;
  1154.         }
  1155.         else
  1156.         {
  1157.             x2 = x + pts->x;
  1158.             y2 = y + pts->y;
  1159.         }
  1160.         x = x2;
  1161.         y = y2;
  1162.         LINE_SORT(x1, y1, x2, y2);
  1163.         if (LINE_OVERLAP(cursor, x1, y1, x2, y2, extra))
  1164.         {
  1165.             miSpriteRemoveCursor (pDrawable->pScreen);
  1166.             break;
  1167.         }
  1168.         }
  1169.     }
  1170.     }
  1171.     GC_OP_PROLOGUE (pGC);
  1172.  
  1173.     (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, pptInit);
  1174.  
  1175.     GC_OP_EPILOGUE (pGC);
  1176. }
  1177.  
  1178. static void
  1179. miSpritePolySegment(pDrawable, pGC, nseg, pSegs)
  1180.     DrawablePtr pDrawable;
  1181.     GCPtr     pGC;
  1182.     int        nseg;
  1183.     xSegment    *pSegs;
  1184. {
  1185.     int        n;
  1186.     register xSegment *segs;
  1187.     BoxPtr  cursor;
  1188.     int        x1, y1, x2, y2;
  1189.     int        extra;
  1190.  
  1191.     GC_SETUP(pDrawable, pGC);
  1192.  
  1193.     if (nseg && GC_CHECK((WindowPtr) pDrawable))
  1194.     {
  1195.     cursor = &pScreenPriv->saved;
  1196.     extra = pGC->lineWidth >> 1;
  1197.     if (pGC->capStyle == CapProjecting)
  1198.         extra = pGC->lineWidth;
  1199.     for (segs = pSegs, n = nseg; n--; segs++)
  1200.     {
  1201.         x1 = segs->x1 + pDrawable->x;
  1202.         y1 = segs->y1 + pDrawable->y;
  1203.         x2 = segs->x2 + pDrawable->x;
  1204.         y2 = segs->y2 + pDrawable->y;
  1205.         LINE_SORT(x1, y1, x2, y2);
  1206.         if (LINE_OVERLAP(cursor, x1, y1, x2, y2, extra))
  1207.         {
  1208.         miSpriteRemoveCursor (pDrawable->pScreen);
  1209.         break;
  1210.         }
  1211.     }
  1212.     }
  1213.  
  1214.     GC_OP_PROLOGUE (pGC);
  1215.  
  1216.     (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, pSegs);
  1217.  
  1218.     GC_OP_EPILOGUE (pGC);
  1219. }
  1220.  
  1221. static void
  1222. miSpritePolyRectangle(pDrawable, pGC, nrects, pRects)
  1223.     DrawablePtr    pDrawable;
  1224.     GCPtr    pGC;
  1225.     int        nrects;
  1226.     xRectangle    *pRects;
  1227. {
  1228.     register xRectangle *rects;
  1229.     BoxPtr  cursor;
  1230.     int        lw;
  1231.     int        n;
  1232.     int     x1, y1, x2, y2;
  1233.     
  1234.     GC_SETUP (pDrawable, pGC);
  1235.  
  1236.     if (GC_CHECK((WindowPtr) pDrawable))
  1237.     {
  1238.     lw = pGC->lineWidth >> 1;
  1239.     cursor = &pScreenPriv->saved;
  1240.     for (rects = pRects, n = nrects; n--; rects++)
  1241.     {
  1242.         x1 = rects->x + pDrawable->x;
  1243.         y1 = rects->y + pDrawable->y;
  1244.         x2 = x1 + (int)rects->width;
  1245.         y2 = y1 + (int)rects->height;
  1246.         if (LINE_OVERLAP(cursor, x1, y1, x2, y1, lw) ||
  1247.         LINE_OVERLAP(cursor, x2, y1, x2, y2, lw) ||
  1248.         LINE_OVERLAP(cursor, x1, y2, x2, y2, lw) ||
  1249.         LINE_OVERLAP(cursor, x1, y1, x1, y2, lw))
  1250.         {
  1251.         miSpriteRemoveCursor (pDrawable->pScreen);
  1252.         break;
  1253.         }
  1254.     }
  1255.     }
  1256.  
  1257.     GC_OP_PROLOGUE (pGC);
  1258.  
  1259.     (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, pRects);
  1260.  
  1261.     GC_OP_EPILOGUE (pGC);
  1262. }
  1263.  
  1264. static void
  1265. miSpritePolyArc(pDrawable, pGC, narcs, parcs)
  1266.     DrawablePtr    pDrawable;
  1267.     register GCPtr    pGC;
  1268.     int        narcs;
  1269.     xArc    *parcs;
  1270. {
  1271.     BoxPtr  cursor;
  1272.     int        lw;
  1273.     int        n;
  1274.     register xArc *arcs;
  1275.     
  1276.     GC_SETUP (pDrawable, pGC);
  1277.  
  1278.     if (GC_CHECK((WindowPtr) pDrawable))
  1279.     {
  1280.     lw = pGC->lineWidth >> 1;
  1281.     cursor = &pScreenPriv->saved;
  1282.     for (arcs = parcs, n = narcs; n--; arcs++)
  1283.     {
  1284.         if (ORG_OVERLAP (cursor, pDrawable->x, pDrawable->y,
  1285.                  arcs->x - lw, arcs->y - lw,
  1286.                  (int) arcs->width + pGC->lineWidth,
  1287.                   (int) arcs->height + pGC->lineWidth))
  1288.         {
  1289.         miSpriteRemoveCursor (pDrawable->pScreen);
  1290.         break;
  1291.         }
  1292.     }
  1293.     }
  1294.  
  1295.     GC_OP_PROLOGUE (pGC);
  1296.  
  1297.     (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, parcs);
  1298.  
  1299.     GC_OP_EPILOGUE (pGC);
  1300. }
  1301.  
  1302. static void
  1303. miSpriteFillPolygon(pDrawable, pGC, shape, mode, count, pPts)
  1304.     register DrawablePtr pDrawable;
  1305.     register GCPtr    pGC;
  1306.     int            shape, mode;
  1307.     int            count;
  1308.     DDXPointPtr        pPts;
  1309. {
  1310.     int x, y, minx, miny, maxx, maxy;
  1311.     register DDXPointPtr pts;
  1312.     int n;
  1313.  
  1314.     GC_SETUP (pDrawable, pGC);
  1315.  
  1316.     if (count && GC_CHECK((WindowPtr) pDrawable))
  1317.     {
  1318.     x = pDrawable->x;
  1319.     y = pDrawable->y;
  1320.     pts = pPts;
  1321.     minx = maxx = pts->x;
  1322.     miny = maxy = pts->y;
  1323.     pts++;
  1324.     n = count - 1;
  1325.  
  1326.     if (mode == CoordModeOrigin)
  1327.     {
  1328.         for (; n--; pts++)
  1329.         {
  1330.         if (pts->x < minx)
  1331.             minx = pts->x;
  1332.         else if (pts->x > maxx)
  1333.             maxx = pts->x;
  1334.         if (pts->y < miny)
  1335.             miny = pts->y;
  1336.         else if (pts->y > maxy)
  1337.             maxy = pts->y;
  1338.         }
  1339.         minx += x;
  1340.         miny += y;
  1341.         maxx += x;
  1342.         maxy += y;
  1343.     }
  1344.     else
  1345.     {
  1346.         x += minx;
  1347.         y += miny;
  1348.         minx = maxx = x;
  1349.         miny = maxy = y;
  1350.         for (; n--; pts++)
  1351.         {
  1352.         x += pts->x;
  1353.         y += pts->y;
  1354.         if (x < minx)
  1355.             minx = x;
  1356.         else if (x > maxx)
  1357.             maxx = x;
  1358.         if (y < miny)
  1359.             miny = y;
  1360.         else if (y > maxy)
  1361.             maxy = y;
  1362.         }
  1363.     }
  1364.     if (BOX_OVERLAP(&pScreenPriv->saved,minx,miny,maxx,maxy))
  1365.         miSpriteRemoveCursor (pDrawable->pScreen);
  1366.     }
  1367.  
  1368.     GC_OP_PROLOGUE (pGC);
  1369.  
  1370.     (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pPts);
  1371.  
  1372.     GC_OP_EPILOGUE (pGC);
  1373. }
  1374.  
  1375. static void
  1376. miSpritePolyFillRect(pDrawable, pGC, nrectFill, prectInit)
  1377.     DrawablePtr pDrawable;
  1378.     GCPtr    pGC;
  1379.     int        nrectFill;     /* number of rectangles to fill */
  1380.     xRectangle    *prectInit;      /* Pointer to first rectangle to fill */
  1381. {
  1382.     GC_SETUP(pDrawable, pGC);
  1383.  
  1384.     if (GC_CHECK((WindowPtr) pDrawable))
  1385.     {
  1386.     register int        nRect;
  1387.     register xRectangle *pRect;
  1388.     register int        xorg, yorg;
  1389.  
  1390.     xorg = pDrawable->x;
  1391.     yorg = pDrawable->y;
  1392.  
  1393.     for (nRect = nrectFill, pRect = prectInit; nRect--; pRect++) {
  1394.         if (ORGRECT_OVERLAP(&pScreenPriv->saved,xorg,yorg,pRect)){
  1395.         miSpriteRemoveCursor(pDrawable->pScreen);
  1396.         break;
  1397.         }
  1398.     }
  1399.     }
  1400.  
  1401.     GC_OP_PROLOGUE (pGC);
  1402.  
  1403.     (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrectFill, prectInit);
  1404.  
  1405.     GC_OP_EPILOGUE (pGC);
  1406. }
  1407.  
  1408. static void
  1409. miSpritePolyFillArc(pDrawable, pGC, narcs, parcs)
  1410.     DrawablePtr    pDrawable;
  1411.     GCPtr    pGC;
  1412.     int        narcs;
  1413.     xArc    *parcs;
  1414. {
  1415.     GC_SETUP(pDrawable, pGC);
  1416.  
  1417.     if (GC_CHECK((WindowPtr) pDrawable))
  1418.     {
  1419.     register int    n;
  1420.     BoxPtr        cursor;
  1421.     register xArc *arcs;
  1422.  
  1423.     cursor = &pScreenPriv->saved;
  1424.  
  1425.     for (arcs = parcs, n = narcs; n--; arcs++)
  1426.     {
  1427.         if (ORG_OVERLAP(cursor, pDrawable->x, pDrawable->y,
  1428.                 arcs->x, arcs->y,
  1429.                  (int) arcs->width, (int) arcs->height))
  1430.         {
  1431.         miSpriteRemoveCursor (pDrawable->pScreen);
  1432.         break;
  1433.         }
  1434.     }
  1435.     }
  1436.  
  1437.     GC_OP_PROLOGUE (pGC);
  1438.  
  1439.     (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, parcs);
  1440.  
  1441.     GC_OP_EPILOGUE (pGC);
  1442. }
  1443.  
  1444. /*
  1445.  * general Poly/Image text function.  Extract glyph information,
  1446.  * compute bounding box and remove cursor if it is overlapped.
  1447.  */
  1448.  
  1449. static Bool
  1450. miSpriteTextOverlap (pDraw, font, x, y, n, charinfo, imageblt, w, cursorBox)
  1451.     DrawablePtr   pDraw;
  1452.     FontPtr      font;
  1453.     int          x, y;
  1454.     unsigned long n;
  1455.     CharInfoPtr   *charinfo;
  1456.     Bool      imageblt;
  1457.     unsigned int  w;
  1458.     BoxPtr      cursorBox;
  1459. {
  1460.     ExtentInfoRec extents;
  1461.  
  1462.     x += pDraw->x;
  1463.     y += pDraw->y;
  1464.  
  1465.     if (font->pFI->minbounds.metrics.characterWidth >= 0)
  1466.     {
  1467.     /* compute an approximate (but covering) bounding box */
  1468.     if (!imageblt || (charinfo[0]->metrics.leftSideBearing < 0))
  1469.         extents.overallLeft = charinfo[0]->metrics.leftSideBearing;
  1470.     else
  1471.         extents.overallLeft = 0;
  1472.     if (w)
  1473.         extents.overallRight = w - charinfo[n-1]->metrics.characterWidth;
  1474.     else
  1475.         extents.overallRight = font->pFI->maxbounds.metrics.characterWidth
  1476.                     * (n - 1);
  1477.     if (imageblt && (charinfo[n-1]->metrics.characterWidth >
  1478.              charinfo[n-1]->metrics.rightSideBearing))
  1479.         extents.overallRight += charinfo[n-1]->metrics.characterWidth;
  1480.     else
  1481.         extents.overallRight += charinfo[n-1]->metrics.rightSideBearing;
  1482.     if (imageblt &&
  1483.         (font->pFI->fontAscent > font->pFI->maxbounds.metrics.ascent))
  1484.         extents.overallAscent = font->pFI->fontAscent;
  1485.     else
  1486.         extents.overallAscent = font->pFI->maxbounds.metrics.ascent;
  1487.     if (imageblt &&
  1488.         (font->pFI->fontDescent > font->pFI->maxbounds.metrics.descent))
  1489.         extents.overallDescent = font->pFI->fontDescent;
  1490.     else
  1491.         extents.overallDescent = font->pFI->maxbounds.metrics.descent;
  1492.     if (!BOX_OVERLAP(cursorBox,
  1493.              x + extents.overallLeft,
  1494.              y - extents.overallAscent,
  1495.              x + extents.overallRight,
  1496.              y + extents.overallDescent))
  1497.         return FALSE;
  1498.     else if (imageblt && w)
  1499.         return TRUE;
  1500.     /* if it does overlap, fall through and compute exactly, because
  1501.      * taking down the cursor is expensive enough to make this worth it
  1502.      */
  1503.     }
  1504.     QueryGlyphExtents(font, charinfo, n, &extents);
  1505.     if (imageblt)
  1506.     {
  1507.     if (extents.overallWidth > extents.overallRight)
  1508.         extents.overallRight = extents.overallWidth;
  1509.     if (extents.overallWidth < extents.overallLeft)
  1510.         extents.overallLeft = extents.overallWidth;
  1511.     if (extents.overallLeft > 0)
  1512.         extents.overallLeft = 0;
  1513.     if (extents.fontAscent > extents.overallAscent)
  1514.         extents.overallAscent = extents.fontAscent;
  1515.     if (extents.fontDescent > extents.overallDescent)
  1516.         extents.overallDescent = extents.fontDescent;
  1517.     }
  1518.     return (BOX_OVERLAP(cursorBox,
  1519.             x + extents.overallLeft,
  1520.             y - extents.overallAscent,
  1521.             x + extents.overallRight,
  1522.             y + extents.overallDescent));
  1523. }
  1524.  
  1525. /*
  1526.  * values for textType:
  1527.  */
  1528. #define TT_POLY8   0
  1529. #define TT_IMAGE8  1
  1530. #define TT_POLY16  2
  1531. #define TT_IMAGE16 3
  1532.  
  1533. static int 
  1534. miSpriteText (pDraw, pGC, x, y, count, chars, fontEncoding, textType, cursorBox)
  1535.     DrawablePtr        pDraw;
  1536.     GCPtr        pGC;
  1537.     int            x,
  1538.             y;
  1539.     unsigned long    count;
  1540.     char        *chars;
  1541.     FontEncoding    fontEncoding;
  1542.     Bool        textType;
  1543.     BoxPtr        cursorBox;
  1544. {
  1545.     CharInfoPtr *charinfo;
  1546.     register CharInfoPtr *info;
  1547.     unsigned long n, i;
  1548.     unsigned int w;
  1549.     void          (*drawFunc)();
  1550.  
  1551.     Bool imageblt;
  1552.  
  1553.     imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16);
  1554.  
  1555.     charinfo = (CharInfoPtr *) ALLOCATE_LOCAL(count * sizeof(CharInfoPtr));
  1556.     if (!charinfo)
  1557.     return x;
  1558.  
  1559.     GetGlyphs(pGC->font, count, (unsigned char *)chars,
  1560.           fontEncoding, &n, charinfo);
  1561.     w = 0;
  1562.     if (!imageblt)
  1563.     for (info = charinfo, i = n; i--; info++)
  1564.         w += (*info)->metrics.characterWidth;
  1565.  
  1566.     if (n != 0) {
  1567.     if (miSpriteTextOverlap(pDraw, pGC->font, x, y, n, charinfo, imageblt, w, cursorBox))
  1568.         miSpriteRemoveCursor(pDraw->pScreen);
  1569.  
  1570. #ifdef AVOID_GLYPHBLT
  1571.     /*
  1572.      * On displays like Apollos, which do not optimize the GlyphBlt functions because they
  1573.      * convert fonts to their internal form in RealizeFont and optimize text directly, we
  1574.      * want to invoke the text functions here, not the GlyphBlt functions.
  1575.      */
  1576.     switch (textType)
  1577.     {
  1578.     case TT_POLY8:
  1579.         drawFunc = pGC->ops->PolyText8;
  1580.         break;
  1581.     case TT_IMAGE8:
  1582.         drawFunc = pGC->ops->ImageText8;
  1583.         break;
  1584.     case TT_POLY16:
  1585.         drawFunc = pGC->ops->PolyText16;
  1586.         break;
  1587.     case TT_IMAGE16:
  1588.         drawFunc = pGC->ops->ImageText16;
  1589.         break;
  1590.     }
  1591.     (*drawFunc) (pDraw, pGC, x, y, (int) count, chars);
  1592. #else /* don't AVOID_GLYPHBLT */
  1593.     /*
  1594.      * On the other hand, if the device does use GlyphBlt ultimately to do text, we
  1595.      * don't want to slow it down by invoking the text functions and having them call
  1596.      * GetGlyphs all over again, so we go directly to the GlyphBlt functions here.
  1597.      */
  1598.     drawFunc = imageblt ? pGC->ops->ImageGlyphBlt : pGC->ops->PolyGlyphBlt;
  1599.     (*drawFunc) (pDraw, pGC, x, y, n, charinfo, pGC->font->pGlyphs);
  1600. #endif /* AVOID_GLYPHBLT */
  1601.     }
  1602.     DEALLOCATE_LOCAL(charinfo);
  1603.     return x + w;
  1604. }
  1605.  
  1606. static int
  1607. miSpritePolyText8(pDrawable, pGC, x, y, count, chars)
  1608.     DrawablePtr pDrawable;
  1609.     GCPtr    pGC;
  1610.     int        x, y;
  1611.     int     count;
  1612.     char    *chars;
  1613. {
  1614.     int    ret;
  1615.  
  1616.     GC_SETUP (pDrawable, pGC);
  1617.  
  1618.     GC_OP_PROLOGUE (pGC);
  1619.  
  1620.     if (GC_CHECK((WindowPtr) pDrawable))
  1621.     ret = miSpriteText (pDrawable, pGC, x, y, (unsigned long)count, chars,
  1622.                 Linear8Bit, TT_POLY8, &pScreenPriv->saved);
  1623.     else
  1624.     ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);
  1625.  
  1626.     GC_OP_EPILOGUE (pGC);
  1627.     return ret;
  1628. }
  1629.  
  1630. static int
  1631. miSpritePolyText16(pDrawable, pGC, x, y, count, chars)
  1632.     DrawablePtr pDrawable;
  1633.     GCPtr    pGC;
  1634.     int        x, y;
  1635.     int        count;
  1636.     unsigned short *chars;
  1637. {
  1638.     int    ret;
  1639.  
  1640.     GC_SETUP(pDrawable, pGC);
  1641.  
  1642.     GC_OP_PROLOGUE (pGC);
  1643.  
  1644.     if (GC_CHECK((WindowPtr) pDrawable))
  1645.     ret = miSpriteText (pDrawable, pGC, x, y, (unsigned long)count,
  1646.                 (char *)chars,
  1647.                 pGC->font->pFI->lastRow == 0 ?
  1648.                 Linear16Bit : TwoD16Bit, TT_POLY16, &pScreenPriv->saved);
  1649.     else
  1650.     ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);
  1651.  
  1652.     GC_OP_EPILOGUE (pGC);
  1653.     return ret;
  1654. }
  1655.  
  1656. static void
  1657. miSpriteImageText8(pDrawable, pGC, x, y, count, chars)
  1658.     DrawablePtr pDrawable;
  1659.     GCPtr    pGC;
  1660.     int        x, y;
  1661.     int        count;
  1662.     char    *chars;
  1663. {
  1664.     GC_SETUP(pDrawable, pGC);
  1665.  
  1666.     GC_OP_PROLOGUE (pGC);
  1667.  
  1668.     if (GC_CHECK((WindowPtr) pDrawable))
  1669.     (void) miSpriteText (pDrawable, pGC, x, y, (unsigned long)count,
  1670.                  chars, Linear8Bit, TT_IMAGE8, &pScreenPriv->saved);
  1671.     else
  1672.     (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);
  1673.  
  1674.     GC_OP_EPILOGUE (pGC);
  1675. }
  1676.  
  1677. static void
  1678. miSpriteImageText16(pDrawable, pGC, x, y, count, chars)
  1679.     DrawablePtr pDrawable;
  1680.     GCPtr    pGC;
  1681.     int        x, y;
  1682.     int        count;
  1683.     unsigned short *chars;
  1684. {
  1685.     GC_SETUP(pDrawable, pGC);
  1686.  
  1687.     GC_OP_PROLOGUE (pGC);
  1688.  
  1689.     if (GC_CHECK((WindowPtr) pDrawable))
  1690.     (void) miSpriteText (pDrawable, pGC, x, y, (unsigned long)count,
  1691.                  (char *)chars,
  1692.                 pGC->font->pFI->lastRow == 0 ?
  1693.                 Linear16Bit : TwoD16Bit, TT_IMAGE16, &pScreenPriv->saved);
  1694.     else
  1695.     (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);
  1696.  
  1697.     GC_OP_EPILOGUE (pGC);
  1698. }
  1699.  
  1700. static void
  1701. miSpriteImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
  1702.     DrawablePtr pDrawable;
  1703.     GC         *pGC;
  1704.     int     x, y;
  1705.     unsigned long nglyph;
  1706.     CharInfoPtr *ppci;        /* array of character info */
  1707.     pointer     pglyphBase;    /* start of array of glyphs */
  1708. {
  1709.     GC_SETUP(pDrawable, pGC);
  1710.  
  1711.     GC_OP_PROLOGUE (pGC);
  1712.  
  1713.     if (GC_CHECK((WindowPtr) pDrawable) &&
  1714.     miSpriteTextOverlap (pDrawable, pGC->font, x, y, nglyph, ppci, TRUE, 0, &pScreenPriv->saved))
  1715.     {
  1716.     miSpriteRemoveCursor(pDrawable->pScreen);
  1717.     }
  1718.     (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
  1719.  
  1720.     GC_OP_EPILOGUE (pGC);
  1721. }
  1722.  
  1723. static void
  1724. miSpritePolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
  1725.     DrawablePtr pDrawable;
  1726.     GCPtr    pGC;
  1727.     int     x, y;
  1728.     unsigned long nglyph;
  1729.     CharInfoPtr *ppci;        /* array of character info */
  1730.     char     *pglyphBase;    /* start of array of glyphs */
  1731. {
  1732.     GC_SETUP (pDrawable, pGC);
  1733.  
  1734.     GC_OP_PROLOGUE (pGC);
  1735.  
  1736.     if (GC_CHECK((WindowPtr) pDrawable) &&
  1737.     miSpriteTextOverlap (pDrawable, pGC->font, x, y, nglyph, ppci, FALSE, 0, &pScreenPriv->saved))
  1738.     {
  1739.     miSpriteRemoveCursor(pDrawable->pScreen);
  1740.     }
  1741.     (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
  1742.  
  1743.     GC_OP_EPILOGUE (pGC);
  1744. }
  1745.  
  1746. static void
  1747. miSpritePushPixels(pGC, pBitMap, pDrawable, w, h, x, y)
  1748.     GCPtr    pGC;
  1749.     PixmapPtr    pBitMap;
  1750.     DrawablePtr pDrawable;
  1751.     int        w, h, x, y;
  1752. {
  1753.     GC_SETUP(pDrawable, pGC);
  1754.  
  1755.     if (GC_CHECK((WindowPtr) pDrawable) &&
  1756.     ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y,x,y,w,h))
  1757.     {
  1758.     miSpriteRemoveCursor (pDrawable->pScreen);
  1759.     }
  1760.  
  1761.     GC_OP_PROLOGUE (pGC);
  1762.  
  1763.     (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, w, h, x, y);
  1764.  
  1765.     GC_OP_EPILOGUE (pGC);
  1766. }
  1767.  
  1768. /*
  1769.  * I don't expect this routine will ever be called, as the GC
  1770.  * will have been unwrapped for the line drawing
  1771.  */
  1772.  
  1773. static void
  1774. miSpriteLineHelper()
  1775. {
  1776.     FatalError("miSpriteLineHelper called\n");
  1777. }
  1778.  
  1779. /*
  1780.  * miPointer interface routines
  1781.  */
  1782.  
  1783. #define SPRITE_PAD  8
  1784.  
  1785. static Bool
  1786. miSpriteRealizeCursor (pScreen, pCursor)
  1787.     ScreenPtr    pScreen;
  1788.     CursorPtr    pCursor;
  1789. {
  1790.     miSpriteScreenPtr    pScreenPriv;
  1791.  
  1792.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  1793.     return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor);
  1794. }
  1795.  
  1796. static Bool
  1797. miSpriteUnrealizeCursor (pScreen, pCursor)
  1798.     ScreenPtr    pScreen;
  1799.     CursorPtr    pCursor;
  1800. {
  1801.     miSpriteScreenPtr    pScreenPriv;
  1802.  
  1803.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  1804.     return (*pScreenPriv->funcs->UnrealizeCursor) (pScreen, pCursor);
  1805. }
  1806.  
  1807. static void
  1808. miSpriteDisplayCursor (pScreen, pCursor, x, y)
  1809.     ScreenPtr    pScreen;
  1810.     CursorPtr    pCursor;
  1811. {
  1812.     miSpriteScreenPtr    pScreenPriv;
  1813.  
  1814.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  1815.     pScreenPriv->shouldBeUp = TRUE;
  1816.     if (pScreenPriv->x == x &&
  1817.     pScreenPriv->y == y &&
  1818.     pScreenPriv->pCursor == pCursor &&
  1819.     !pScreenPriv->checkPixels)
  1820.     {
  1821.     return;
  1822.     }
  1823.     pScreenPriv->x = x;
  1824.     pScreenPriv->y = y;
  1825.     if (pScreenPriv->checkPixels || pScreenPriv->pCursor != pCursor)
  1826.     {
  1827.     pScreenPriv->pCursor = pCursor;
  1828.     miSpriteFindColors (pScreen);
  1829.     }
  1830.     else
  1831.     pScreenPriv->pCursor = pCursor;
  1832.     if (pScreenPriv->isUp) {
  1833.     int    sx, sy;
  1834.     /*
  1835.      * check to see if the old saved region
  1836.      * encloses the new sprite, in which case we use
  1837.      * the flicker-free MoveCursor primitive.
  1838.      */
  1839.     sx = pScreenPriv->x - (int)pCursor->bits->xhot;
  1840.     sy = pScreenPriv->y - (int)pCursor->bits->yhot;
  1841.     if (sx + (int) pCursor->bits->width >= pScreenPriv->saved.x1 &&
  1842.         sx < pScreenPriv->saved.x2 &&
  1843.         sy + (int) pCursor->bits->height >= pScreenPriv->saved.y1 &&
  1844.         sy < pScreenPriv->saved.y2 &&
  1845.         (int) pCursor->bits->width + (2 * SPRITE_PAD) ==
  1846.         pScreenPriv->saved.x2 - pScreenPriv->saved.x1 &&
  1847.         (int) pCursor->bits->height + (2 * SPRITE_PAD) ==
  1848.         pScreenPriv->saved.y2 - pScreenPriv->saved.y1
  1849.         )
  1850.     {
  1851.         pScreenPriv->isUp = FALSE;
  1852.         if (!(sx >= pScreenPriv->saved.x1 &&
  1853.                 sx + (int)pCursor->bits->width < pScreenPriv->saved.x2 &&
  1854.                 sy >= pScreenPriv->saved.y1 &&
  1855.                 sy + (int)pCursor->bits->height < pScreenPriv->saved.y2))
  1856.         {
  1857.         int oldx1, oldy1, dx, dy;
  1858.  
  1859.         oldx1 = pScreenPriv->saved.x1;
  1860.         oldy1 = pScreenPriv->saved.y1;
  1861.         dx = oldx1 - (sx - SPRITE_PAD);
  1862.         dy = oldy1 - (sy - SPRITE_PAD);
  1863.         pScreenPriv->saved.x1 -= dx;
  1864.         pScreenPriv->saved.y1 -= dy;
  1865.         pScreenPriv->saved.x2 -= dx;
  1866.         pScreenPriv->saved.y2 -= dy;
  1867.         (void) (*pScreenPriv->funcs->ChangeSave) (pScreen,
  1868.                 pScreenPriv->saved.x1,
  1869.                  pScreenPriv->saved.y1,
  1870.                 pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
  1871.                 pScreenPriv->saved.y2 - pScreenPriv->saved.y1,
  1872.                 dx, dy);
  1873.         }
  1874.         (void) (*pScreenPriv->funcs->MoveCursor) (pScreen, pCursor,
  1875.                   pScreenPriv->saved.x1,
  1876.                    pScreenPriv->saved.y1,
  1877.                   pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
  1878.                   pScreenPriv->saved.y2 - pScreenPriv->saved.y1,
  1879.                   sx - pScreenPriv->saved.x1,
  1880.                   sy - pScreenPriv->saved.y1,
  1881.                   pScreenPriv->colors[SOURCE_COLOR].pixel,
  1882.                   pScreenPriv->colors[MASK_COLOR].pixel);
  1883.         pScreenPriv->isUp = TRUE;
  1884.     }
  1885.     else
  1886.     {
  1887.         miSpriteRemoveCursor (pScreen);
  1888.     }
  1889.     }
  1890.     if (!pScreenPriv->isUp && pScreenPriv->pCursor)
  1891.     miSpriteRestoreCursor (pScreen);
  1892. }
  1893.  
  1894. /*ARGSUSED*/
  1895. static void
  1896. miSpriteUndisplayCursor (pScreen, pCursor)
  1897.     ScreenPtr    pScreen;
  1898.     CursorPtr    pCursor;
  1899. {
  1900.     miSpriteScreenPtr   pScreenPriv;
  1901.  
  1902.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  1903.     pScreenPriv->shouldBeUp = FALSE;
  1904.     if (pScreenPriv->isUp)
  1905.     miSpriteRemoveCursor (pScreen);
  1906. }
  1907.  
  1908. /*
  1909.  * undraw/draw cursor
  1910.  */
  1911.  
  1912. static void
  1913. miSpriteRemoveCursor (pScreen)
  1914.     ScreenPtr    pScreen;
  1915. {
  1916.     miSpriteScreenPtr   pScreenPriv;
  1917.  
  1918.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  1919.     pScreenPriv->isUp = FALSE;
  1920.     if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pScreen,
  1921.                      pScreenPriv->saved.x1,
  1922.                      pScreenPriv->saved.y1,
  1923.                      pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
  1924.                      pScreenPriv->saved.y2 - pScreenPriv->saved.y1))
  1925.     {
  1926.     pScreenPriv->isUp = TRUE;
  1927.     }
  1928. }
  1929.  
  1930. /*
  1931.  * Called from the block handler, restores the cursor
  1932.  * before waiting for something to do.
  1933.  */
  1934.  
  1935. static void
  1936. miSpriteRestoreCursor (pScreen)
  1937.     ScreenPtr    pScreen;
  1938. {
  1939.     miSpriteScreenPtr   pScreenPriv;
  1940.     int            x, y;
  1941.     CursorPtr        pCursor;
  1942.  
  1943.     miSpriteComputeSaved (pScreen);
  1944.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  1945.     pCursor = pScreenPriv->pCursor;
  1946.     x = pScreenPriv->x - (int)pCursor->bits->xhot;
  1947.     y = pScreenPriv->y - (int)pCursor->bits->yhot;
  1948.     if ((*pScreenPriv->funcs->SaveUnderCursor) (pScreen,
  1949.                       pScreenPriv->saved.x1,
  1950.                       pScreenPriv->saved.y1,
  1951.                       pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
  1952.                       pScreenPriv->saved.y2 - pScreenPriv->saved.y1))
  1953.     {
  1954.     if (pScreenPriv->checkPixels)
  1955.         miSpriteFindColors (pScreen);
  1956.     if ((*pScreenPriv->funcs->PutUpCursor) (pScreen, pCursor, x, y,
  1957.                   pScreenPriv->colors[SOURCE_COLOR].pixel,
  1958.                   pScreenPriv->colors[MASK_COLOR].pixel))
  1959.         pScreenPriv->isUp = TRUE;
  1960.     }
  1961. }
  1962.  
  1963. /*
  1964.  * compute the desired area of the screen to save
  1965.  */
  1966.  
  1967. static void
  1968. miSpriteComputeSaved (pScreen)
  1969.     ScreenPtr    pScreen;
  1970. {
  1971.     miSpriteScreenPtr   pScreenPriv;
  1972.     int            x, y, w, h;
  1973.     int            wpad, hpad;
  1974.     CursorPtr        pCursor;
  1975.  
  1976.     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  1977.     pCursor = pScreenPriv->pCursor;
  1978.     x = pScreenPriv->x - (int)pCursor->bits->xhot;
  1979.     y = pScreenPriv->y - (int)pCursor->bits->yhot;
  1980.     w = pCursor->bits->width;
  1981.     h = pCursor->bits->height;
  1982.     wpad = SPRITE_PAD;
  1983.     hpad = SPRITE_PAD;
  1984.     pScreenPriv->saved.x1 = x - wpad;
  1985.     pScreenPriv->saved.y1 = y - hpad;
  1986.     pScreenPriv->saved.x2 = pScreenPriv->saved.x1 + w + wpad * 2;
  1987.     pScreenPriv->saved.y2 = pScreenPriv->saved.y1 + h + hpad * 2;
  1988. }
  1989.